package rule

import (
	"fmt"
	"strings"
)

type ruleReq struct {
	AppId      int32
	Version    string
	Country    string
	UserStatus *int32
}

type Special struct {
	ID         int
	AppId      int32
	Version    string
	Country    string
	UserStatus int32
}

// RuleNode 表示规则树中的一个节点
type RuleNode struct {
	Name     string
	Value    string // 当前节点对应的值（用于调试和匹配）
	Match    func(req ruleReq) bool
	Children []*RuleNode
	Leafs    []*Special
}

// getOrCreateChild 查找或添加子节点
func (n *RuleNode) getOrCreateChild(name string, value string, matchFunc func(req ruleReq) bool) *RuleNode {
	for _, child := range n.Children {
		if child.Name == name && child.Value == value {
			return child
		}
	}
	child := &RuleNode{Name: name, Value: value, Match: matchFunc}
	n.Children = append(n.Children, child)
	return child
}

// buildRuleDAG 构建规则树（DAG）
func buildRuleDAG(specials []*Special) *RuleNode {
	root := &RuleNode{Name: "root"}

	for _, s := range specials {
		appIdVal := fmt.Sprintf("%d", s.AppId)
		appIdNode := root.getOrCreateChild("AppId", appIdVal, func(req ruleReq) bool {
			return req.AppId == s.AppId
		})

		versionNode := appIdNode.getOrCreateChild("Version", s.Version, func(req ruleReq) bool {
			return strings.HasPrefix(req.Version, s.Version)
		})

		countryNode := versionNode.getOrCreateChild("Country", s.Country, func(req ruleReq) bool {
			return req.Country == s.Country
		})

		userStatusVal := fmt.Sprintf("%d", s.UserStatus)
		userNode := countryNode.getOrCreateChild("UserStatus", userStatusVal, func(req ruleReq) bool {
			if req.UserStatus == nil {
				return true
			}
			return *req.UserStatus == s.UserStatus
		})

		userNode.Leafs = append(userNode.Leafs, s)
	}
	return root
}

// MatchLeafs 递归匹配请求，返回所有符合的 Special
func (n *RuleNode) MatchLeafs(req ruleReq, path []string) []*Special {
	if n.Match != nil && !n.Match(req) {
		return nil
	}

	if len(n.Children) == 0 {
		// 可以打印路径
		// fmt.Println("命中路径:", strings.Join(path, " -> "))
		return n.Leafs
	}

	var result []*Special
	for _, child := range n.Children {
		newPath := append(path, fmt.Sprintf("%s=%s", child.Name, child.Value))
		result = append(result, child.MatchLeafs(req, newPath)...)
	}
	return result
}

// ======================= 示例运行 ==========================

func main() {
	userStatus := int32(1)
	specials := []*Special{
		{ID: 1, AppId: 1001, Version: "1.0", Country: "US", UserStatus: 1},
		{ID: 2, AppId: 1001, Version: "1.2", Country: "CN", UserStatus: 1},
		{ID: 3, AppId: 1002, Version: "2.0", Country: "US", UserStatus: 0},
	}

	dag := buildRuleDAG(specials)

	req := ruleReq{
		AppId:      1001,
		Version:    "1.0.5",
		Country:    "US",
		UserStatus: &userStatus,
	}

	result := dag.MatchLeafs(req, []string{"root"})

	for _, item := range result {
		fmt.Printf("✅ 命中 Special ID: %d\n", item.ID)
	}
}
